package com.wsoft.hr.pm.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wsoft.core.validate.ValidList;
import com.wsoft.entity.BaseEntity;
import com.wsoft.hr.pm.entity.HrPmProcessTemplateCardEntity;
import com.wsoft.hr.pm.entity.HrPmProcessTemplateEntity;
import com.wsoft.hr.pm.manager.HrPmProcessTemplateCardManager;
import com.wsoft.hr.pm.manager.HrPmProcessTemplateManager;
import com.wsoft.hr.pm.mapper.HrPmProcessTemplateMapper;
import com.wsoft.hr.pm.query.process.template.HrPmProcessTemplateQuery;
import com.wsoft.hr.pm.query.process.template.HrPmProcessTemplateSaveQuery;
import com.wsoft.hr.pm.query.process.template.HrProcessTemplateCardQuery;
import com.wsoft.hr.pm.service.IHrPmProcessTemplateService;
import com.wsoft.hr.pm.vo.process.template.HrPmProcessTemplateDataVO;
import com.wsoft.hr.pm.vo.process.template.HrPmProcessTemplateVO;
import com.wsoft.hr.pm.vo.process.template.HrProcessTemplateCardVO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 模版考核流程主表 服务实现类
 * </p>
 *
 * @author zhonglj
 * @since 2025年02月28日 18:12:47
 */
@Service
public class HrPmProcessTemplateServiceImpl extends ServiceImpl<HrPmProcessTemplateMapper, HrPmProcessTemplateEntity> implements IHrPmProcessTemplateService {
    @Resource
    private HrPmProcessTemplateManager processTemplateManager;
    @Resource
    private HrPmProcessTemplateCardManager processTemplateCardManager;

    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.SERIALIZABLE)
    public void saveProcess(HrPmProcessTemplateSaveQuery saveQuery) {
        Long templateId = saveQuery.getTemplateId();
        List<HrPmProcessTemplateQuery> templates = saveQuery.getFlowStages();

        List<HrPmProcessTemplateEntity> existTemplate = processTemplateManager.list(
                Wrappers.lambdaQuery(HrPmProcessTemplateEntity.class)
                        .eq(HrPmProcessTemplateEntity::getTemplateId, templateId)
        );

        if (CollUtil.isNotEmpty(existTemplate)) {
            List<Long> existTemplateIds = existTemplate.stream().map(BaseEntity::getId).collect(Collectors.toList());
            // 删除主表原始数据
            processTemplateManager.removeByIds(existTemplateIds);

            // 删除卡片表原始数据
            processTemplateCardManager.remove(
                    Wrappers.lambdaQuery(HrPmProcessTemplateCardEntity.class)
                            .in(HrPmProcessTemplateCardEntity::getPid, existTemplateIds)
            );
        }

        for (HrPmProcessTemplateQuery templateQuery : templates) {
            // 保存主表
            HrPmProcessTemplateEntity processTemplateEntity = Convert.convert(HrPmProcessTemplateEntity.class, templateQuery);
            processTemplateEntity.setTemplateId(templateId);
            processTemplateManager.save(processTemplateEntity);
            Long pid = processTemplateEntity.getId();

            // 保存卡片表
            ValidList<HrProcessTemplateCardQuery> cards = templateQuery.getCards();
            if (CollUtil.isNotEmpty(cards)) {
                List<HrPmProcessTemplateCardEntity> cardEntities = new ArrayList<>();
                String serialUuid = Opt.ofBlankAble(cards.get(0).getSerialUuid()).orElse(IdUtil.fastSimpleUUID());
                for (int i = 0; i < cards.size(); i++) {
                    HrProcessTemplateCardQuery card = cards.get(i);
                    HrPmProcessTemplateCardEntity convert = Convert.convert(HrPmProcessTemplateCardEntity.class, card);
                    convert.setPid(pid);
                    convert.setSerialUuid(serialUuid);
                    cardEntities.add(convert);

                    // 处理序列相关逻辑
                    HrProcessTemplateCardQuery nextCard = i == cards.size() - 1 ? null : cards.get(i + 1);
                    boolean nextCardIsDiffSerial = nextCard != null && card.getSerialSort().intValue() != nextCard.getSerialSort().intValue();
                    // 下一个节点不是同一个序列的节点
                    if (nextCardIsDiffSerial) {
                        serialUuid = Opt.ofBlankAble(nextCard.getSerialUuid()).orElse(IdUtil.fastSimpleUUID());
                    }
                }

                processTemplateCardManager.saveBatch(cardEntities);
            }

        }
    }

    @Override
    public HrPmProcessTemplateDataVO getByTemplateId(Long templateId) {
        HrPmProcessTemplateDataVO resultVO = new HrPmProcessTemplateDataVO();
        List<HrPmProcessTemplateEntity> templateEntities = processTemplateManager.list(
                Wrappers.lambdaQuery(HrPmProcessTemplateEntity.class)
                        .eq(HrPmProcessTemplateEntity::getTemplateId, templateId)
                        .orderByAsc(HrPmProcessTemplateEntity::getSort)
        );

        if (CollUtil.isEmpty(templateEntities)) {
            return resultVO;
        }

        resultVO.setTemplateId(templateId);
        List<HrPmProcessTemplateVO> vos = CollUtil.newArrayList();
        for (HrPmProcessTemplateEntity template : templateEntities) {
            // 设置每一个阶段的卡片
            HrPmProcessTemplateVO processTemplateVO = Convert.convert(HrPmProcessTemplateVO.class, template);

            List<HrPmProcessTemplateCardEntity> processTemplateCard = processTemplateCardManager.list(
                    Wrappers.lambdaQuery(HrPmProcessTemplateCardEntity.class)
                            .eq(HrPmProcessTemplateCardEntity::getPid, template.getId())
                            .orderByAsc(HrPmProcessTemplateCardEntity::getSerialSort)
                            .orderByAsc(HrPmProcessTemplateCardEntity::getParallelSort)
            );
            processTemplateVO.setCards(processTemplateCard.stream()
                    .map(e -> Convert.convert(HrProcessTemplateCardVO.class, e))
                    .collect(Collectors.toList()));

            vos.add(processTemplateVO);
        }

        resultVO.setFlowStages(vos);
        return resultVO;
    }
}
